#include "mc31xx_hal_uart.h"
#include "MC3172.h"

//目前芯片仅支持数据位8，停止位1，无校验
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
{
    uint32_t temp1,temp2;//用于计算时钟
    uint32_t ClockDivision;
    uint32_t UartClock;
    uint32_t reg_iocr=0;

    //校验参数
    assert_param(huart!=NULL);
    assert_param(IS_UART_INSTANCE(huart->Instance));
    
    //计算频率
    temp1=huart->Init.BaudRate*100;
    temp2=SYS_CORE_CLK/temp1;
    if(temp2<2)             {ClockDivision= INTDEV_CLK_IS_CORECLK;UartClock=SYS_CORE_CLK;}
    else if(temp2<4)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2;UartClock=SYS_CORE_CLK/2;}
    else if(temp2<8)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4;UartClock=SYS_CORE_CLK/4;}
    else if(temp2<16)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8;UartClock=SYS_CORE_CLK/8;}
    else if(temp2<32)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16;UartClock=SYS_CORE_CLK/16;}
    else if(temp2<64)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV32;UartClock=SYS_CORE_CLK/32;}
    else if(temp2<128)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV64;UartClock=SYS_CORE_CLK/64;}
    else if(temp2<256)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV128;UartClock=SYS_CORE_CLK/128;}
    else if(temp2<512)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV256;UartClock=SYS_CORE_CLK/256;}
    else if(temp2<1024)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV512;UartClock=SYS_CORE_CLK/512;}
    else if(temp2<2048)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV1024;UartClock=SYS_CORE_CLK/1024;}
    else if(temp2<4096)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2048;UartClock=SYS_CORE_CLK/2048;}
    else if(temp2<8192)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4096;UartClock=SYS_CORE_CLK/4096;}
    else if(temp2<16384)    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8192;UartClock=SYS_CORE_CLK/8192;}
    else                    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16384;UartClock=SYS_CORE_CLK/16384;}
       
    //寄存器配置
    huart->Instance->CR=INTDEV_RUN | INTDEV_IS_GROUP0 | ClockDivision;
    if(huart->Init.PinRxd!=HAL_PIN_UNUSED){
        huart->Instance->ICR=huart->Init.PinRxd-1;
        reg_iocr|=0X3<<((huart->Init.PinRxd-1)<<3);
    }   
    if(huart->Init.PinTxd!=HAL_PIN_UNUSED){
        huart->Instance->OCR=(4<<((huart->Init.PinTxd-1)*4+16))|0x33330000;
        reg_iocr|=1<<((huart->Init.PinTxd-1)<<3);
    }   
    huart->Instance->CR1=0x00000001;            //串口模式
    huart->Instance->CR2=(((UartClock/huart->Init.BaudRate)-1)<<8)+(UartClock/huart->Init.BaudRate)/2-2;
    huart->Instance->IOCR=reg_iocr;

    //接收缓冲指针
    huart->RxFifoPoint=huart->Instance->RWPR&0xF;
      
    return HAL_OK;
}

HAL_StatusTypeDef HAL_UART_SetSpeed(UART_HandleTypeDef *huart,uint32_t BaudRate)
{
    uint32_t temp1,temp2;//用于计算时钟
    uint32_t ClockDivision;
    uint32_t UartClock;

    //校验参数
    assert_param(huart!=NULL);
    assert_param(IS_UART_INSTANCE(huart->Instance));
    
    //计算频率
    huart->Init.BaudRate=BaudRate;
    temp1=huart->Init.BaudRate*100;
    temp2=SYS_CORE_CLK/temp1;
    if(temp2<2)             {ClockDivision= INTDEV_CLK_IS_CORECLK;UartClock=SYS_CORE_CLK;}
    else if(temp2<4)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2;UartClock=SYS_CORE_CLK/2;}
    else if(temp2<8)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4;UartClock=SYS_CORE_CLK/4;}
    else if(temp2<16)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8;UartClock=SYS_CORE_CLK/8;}
    else if(temp2<32)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16;UartClock=SYS_CORE_CLK/16;}
    else if(temp2<64)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV32;UartClock=SYS_CORE_CLK/32;}
    else if(temp2<128)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV64;UartClock=SYS_CORE_CLK/64;}
    else if(temp2<256)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV128;UartClock=SYS_CORE_CLK/128;}
    else if(temp2<512)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV256;UartClock=SYS_CORE_CLK/256;}
    else if(temp2<1024)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV512;UartClock=SYS_CORE_CLK/512;}
    else if(temp2<2048)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV1024;UartClock=SYS_CORE_CLK/1024;}
    else if(temp2<4096)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2048;UartClock=SYS_CORE_CLK/2048;}
    else if(temp2<8192)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4096;UartClock=SYS_CORE_CLK/4096;}
    else if(temp2<16384)    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8192;UartClock=SYS_CORE_CLK/8192;}
    else                    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16384;UartClock=SYS_CORE_CLK/16384;}
       
    //寄存器配置
    huart->Instance->CR=INTDEV_RUN | INTDEV_IS_GROUP0 | ClockDivision;
    huart->Instance->CR2=(((UartClock/huart->Init.BaudRate)-1)<<8)+(UartClock/huart->Init.BaudRate)/2-2;

    return HAL_OK;
}

HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
{
    assert_param(huart!=NULL);
    assert_param(IS_UART_INSTANCE(huart->Instance));

    huart->Instance->IOCR=0U;
    huart->Instance->CR=0U;

    return HAL_OK;
}

/*串口发送
参数：  huart 串口对象指针
        pData   发送缓存指针
        Size    发送长度
        Timeout 发送超时ms 目前无效
返回值： HAL_OK
*/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    assert_param(huart!=NULL);
    assert_param(IS_UART_INSTANCE(huart->Instance));
    assert_param(pData!=NULL);
    
    //数据传输
    while (Size--) {
        while ((huart->Instance->TSR&0xFF)==(((huart->Instance->TSR&0xFF00)>>8)^8)) {};
        *(volatile u32*)(((volatile u32)&huart->Instance->ITDR0)+ ((huart->Instance->TSR&0x7)<<3)) = *pData++;   
    }
    
    return HAL_OK;
}

/*串口接收
参数：  huart 串口对象指针
        pData   接收缓存指针
        Size    接收长度
        Timeout 接收超时ms
返回值： 返回接收到的长度
*/
uint16_t HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    uint16_t count=0;
    uint32_t start_tick=CORE_CNT;
    uint32_t ticks= 1000 * SYS_CORE_CLK_MHZ/4;

    assert_param(huart!=NULL);
    assert_param(IS_UART_INSTANCE(huart->Instance));
    assert_param(pData!=NULL);

    if(Timeout==HAL_WAIT_FOREVER){
        while(count<Size){
            if(huart->RxFifoPoint!=(huart->Instance->RWPR&0xF)){  //写指针发生变化，说明有数据了
                pData[count++]= (*(volatile u32*)(((volatile u32)&huart->Instance->RDR0)+((huart->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据     
                huart->RxFifoPoint=++huart->RxFifoPoint&0x0f;
            }
        }
    }
    else if(Timeout==HAL_NO_WAIT){
        while(count<Size){
            if(huart->RxFifoPoint!=(huart->Instance->RWPR&0xF)){  //写指针发生变化，说明有数据了
                pData[count++]= (*(volatile u32*)(((volatile u32)&huart->Instance->RDR0)+((huart->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据     
                huart->RxFifoPoint=++huart->RxFifoPoint&0x0f;
            }
            else{
                break;
            }
        }
    }
    else{
        while(count<Size){
            if(huart->RxFifoPoint!=(huart->Instance->RWPR&0xF)){  //写指针发生变化，说明有数据了
                pData[count++]= (*(volatile u32*)(((volatile u32)&huart->Instance->RDR0)+((huart->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据     
                huart->RxFifoPoint=++huart->RxFifoPoint&0x0f;
            }
            if(CORE_CNT-start_tick>=ticks) {
                start_tick=CORE_CNT;
                Timeout--;
                if(Timeout==0){
                    break;
                }
            }
        }
    }

    return count;
}

